package com.bkhc.business.service;

import com.alibaba.excel.annotation.ExcelProperty;
import com.bkhc.business.entity.*;
import com.bkhc.business.entity.vo.ApplyInfomation;
import com.bkhc.business.entity.vo.Order;
import com.bkhc.business.entity.vo.OrderExcelItem;
import com.bkhc.business.entity.vo.OrderItem;
import com.bkhc.business.repository.*;
import com.bkhc.common.entity.User;
import com.bkhc.common.entity.UserRole;
import com.bkhc.common.permissions.bean.RoleDetail;
import com.bkhc.common.permissions.bean.UserPermission;
import com.bkhc.common.repository.UmcRepository;
import com.bkhc.common.repository.UserRepository;
import com.bkhc.common.repository.UserRoleRepository;
import com.bkhc.common.service.UserService;
import com.bkhc.common.util.CommonUtil;
import com.bkhc.common.util.MyBeanUtils;
import com.bkhc.common.util.response.PageUtil;
import com.bkhc.common.util.response.ResultCode;
import com.bkhc.common.util.response.ResultJson;
import com.bkhc.common.vo.OrderVo;
import com.bkhc.common.vo.UserBean;
import org.checkerframework.checker.units.qual.C;
import org.ehcache.impl.internal.concurrent.ConcurrentHashMap;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.*;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import javax.servlet.http.HttpServletRequest;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class BusinessService {

    @Autowired
    private CustomerRepository repository;

    @Autowired
    private MemberRepository memberrepository;

    @Autowired
    private GroupRepository groupRepository;

    @Autowired
    private UserRepository userRepository;

    @Autowired
    private UmcRepository umcRepository;

    @Autowired
    private UserRoleRepository userRoleRepository;

    @PersistenceContext
    private EntityManager entityManager;

    @Autowired
    private UserService userService;

    @Autowired
    private CustomerLevelWorkFlowRepository customerLevelWorkFlowRepository;

    @Autowired
    private CustomerRepository customerRepository;

    @Autowired
    private BusinessApplyRecordRepository businessApplyRecordRepository;

    @Autowired
    private ProductRepository productRepository;

    @Autowired
    private OrderRepository orderRepository;

    @Autowired
    private OrderService orderService;


    @Autowired
    private BusinessPriceAccountRepository accountRepository;

    private static Map<String,Integer> map = new ConcurrentHashMap<>();


    public ResultJson<?> queryCustomerByGroup(Customer customer, int pageIndex, int pageSize) {
        if(customer == null){
            customer = new Customer();
        }
        UserBean crruentUser = CommonUtil.getCrruentUser();
        UserPermission userPermission = userService.queryUserPermission(crruentUser.getUserId());
        List<RoleDetail> roles = userPermission.getRoles();
        if(CollectionUtils.isEmpty(roles)){
            return null;
        }
        boolean isManager = roles.stream().anyMatch(roleDetail -> "manager".equals(roleDetail.getRole_code()));
        boolean isAdmin = roles.stream().anyMatch(roleDetail -> "admin".equals(roleDetail.getRole_code()));

        boolean isBusiness = roles.stream().anyMatch(roleDetail -> "business".equals(roleDetail.getRole_code()));
        if(isManager){
            Group group = groupRepository.findByManager(crruentUser.getUserId());
            customer.setGroupCode(group.getGroupCode()); ;
        }
        if(isBusiness) {
            Member member = memberrepository.findByUserId(crruentUser.getUserId());
            customer.setInviteCode(member.getInviteCode());
        }
        Sort.Order orders = new Sort.Order(Sort.Direction.DESC, "updateDate");
        PageRequest pageRequest = PageRequest.of(pageIndex - 1, pageSize, Sort.by(orders));
        Page<Customer> page = repository.findAll(customer, pageRequest);
        page.getContent().forEach(v->{
            v.setIdentityName(getIdentity(v.getIdentity()));
        });
        PageUtil pageUtil = new PageUtil(page);
        ResultJson<PageUtil> resultJson = ResultJson.success();
        resultJson.setData(pageUtil);
        return resultJson;
    }

    private String getIdentity(String identity){
        switch (identity){
            case "market":
                return "市场";
            case "owner":
                return "业主";
            case "agent":
                return "代理商";
            case "distributor":
                return "经销商";
            case "subcontractor":
                return "分包商";
            case "generalContractor":
                return "总包商";
            case "Materials":
                return "建材";
            case "Medicine ":
                return "医药";
            case "Electron":
                return "电子";
            default:

            return null;
        }
    }


    public ResultJson<?> updateCustomeridentity(Customer customer) {
        Customer old = repository.findByUserId(customer.getUserId());
        if (old == null) {
            ResultJson<Page<Customer>> resultJson = ResultJson.failure(ResultCode.ISEXIT_RESURCE);
            return resultJson;
        }
        old.setIdentity(customer.getIdentity());
        repository.save(old);
        ResultJson<PageUtil> resultJson = ResultJson.success();
        return resultJson;
    }

    public ResultJson<?> queryMemberByGroup(int pageIndex, int pageSize) {
        Member mem = new Member();
        UserBean crruentUser = CommonUtil.getCrruentUser();
        UserPermission userPermission = userService.queryUserPermission(crruentUser.getUserId());
        List<RoleDetail> roles = userPermission.getRoles();
        if(CollectionUtils.isEmpty(roles)){
            return null;
        }
        boolean isManager = roles.stream().anyMatch(roleDetail -> "manager".equals(roleDetail.getRole_code()));
        boolean isBusiness = roles.stream().anyMatch(roleDetail -> "business".equals(roleDetail.getRole_code()));
        if(!isManager&&!isBusiness){
            return null;
        }
        if(isManager){
            Group group = groupRepository.findByManager(crruentUser.getUserId());
            mem.setGroupCode(group.getGroupCode()); ;
        }
        Sort.Order orders = new Sort.Order(Sort.Direction.DESC, "updateDate");
        PageRequest pageRequest = PageRequest.of(pageIndex - 1, pageSize, Sort.by(orders));
        Page<Member> page = memberrepository.findAll(mem, pageRequest);
        PageUtil pageUtil = new PageUtil(page);
        ResultJson<PageUtil> resultJson = ResultJson.success();
        resultJson.setData(pageUtil);
        return resultJson;
    }

    public ResultJson<?> queryMemberCustomer(String memberId, int pageIndex, int pageSize) {
        Sort.Order orders = new Sort.Order(Sort.Direction.DESC, "updateDate");
        PageRequest pageRequest = PageRequest.of(pageIndex - 1, pageSize, Sort.by(orders));
        Customer cus = new Customer();
        cus.setGroupCode(memberId);
        Page<Customer> page = repository.findAll(cus, pageRequest);
        PageUtil pageUtil = new PageUtil(page);
        ResultJson<PageUtil> resultJson = ResultJson.success();
        resultJson.setData(pageUtil);
        return resultJson;
    }


    public ResultJson<?> assignmentCustomer(Customer customer) {
        Customer old = repository.findByUserId(customer.getUserId());
        if (old == null) {
            ResultJson<Page<Customer>> resultJson = ResultJson.failure(ResultCode.ISEXIT_RESURCE);
            return resultJson;
        }
        old.setInviteCode(customer.getInviteCode());
        repository.save(old);
        ResultJson<PageUtil> resultJson = ResultJson.success();
        return resultJson;
    }

    public ResultJson<?> addMemberByManager(Member member) {
        UserBean u = CommonUtil.getCrruentUser();
        Group group = groupRepository.findByManager(u.getUserId());
        if (group == null) {
            ResultJson<Page<Customer>> resultJson = ResultJson.failure(ResultCode.NORESOURCE);
            return resultJson;
        }
        User user = new User();
        user.setPhone(member.getMobile());
        user.setUsername(member.getUsername());
        user.setFullName(member.getFullName());
        User userEntity = umcRepository.sysUserToUmc(user);
        userRepository.save(userEntity);
        User user1 = userRepository.findByUsername(member.getUsername());
        UserRole ur = new UserRole();
        ur.setUserId(userEntity.getUserId());
        ur.setRoleCode("business");
        ur.setCreator(user1.getUserId());
        ur.setUpdator(user1.getUserId());
        userRoleRepository.save(ur);

        member.setGroupCode(group.getGroupCode());
        member.setUserId(user1.getUserId());
        member.setUsername(user.getUsername());
        member.setCreator(CommonUtil.getCrruentUser().getUserId());
        member.setUpdator(CommonUtil.getCrruentUser().getUserId());
        member.setInviteCode(generateInviteCode());
        memberrepository.save(member);
        ResultJson<PageUtil> resultJson = ResultJson.success();
        return resultJson;
    }

    public ResultJson<?> addGroupByAdmin(Group group) {
        if (StringUtils.isEmpty(group.getManager())) {
            ResultJson<Page<Group>> resultJson = ResultJson.failure(ResultCode.BAD_REQUEST);
            return resultJson;
        }

        Group grouptem2 = groupRepository.findByManager(group.getManager());
        if (grouptem2 != null) {
            ResultJson<Page<Group>> resultJson = ResultJson.failure(ResultCode.ISEXIT_RESURCE);
            return resultJson;
        }
        UserBean u = CommonUtil.getCrruentUser();
        group.setCreator(u.getUserId());
        group.setUpdator(u.getUserId());
        group.setGroupCode(generateGroupCode());
        groupRepository.save(group);

        UserRole ur = new UserRole();
        ur.setUserId(group.getManager());
        ur.setRoleCode("manager");
        ur.setCreator(u.getUserId());
        ur.setUpdator(u.getUserId());
        userRoleRepository.save(ur);
        repository.deleteByUserId(group.getManager());
        ResultJson<PageUtil> resultJson = ResultJson.success();
        return resultJson;
    }

    public ResultJson<?> applyCustomerLevel(Customer customer) {
        if (map.get(customer.getUserId()) != null) {
            return ResultJson.failure(ResultCode.ISEXIT_RESURCE);
        }
        //添加一條申請記錄
        CustomLevelWorkFlow workFlow = new CustomLevelWorkFlow();
        workFlow.setCustomerId(customer.getUserId());
        workFlow.setAuditStatus(1);
        CustomLevelWorkFlow workFlowOld=customerLevelWorkFlowRepository.findByIdAndAuditStatus(customer.getId(),1);
        if (workFlowOld != null) {
            return ResultJson.failure(ResultCode.ISEXIT_RESURCE);
        }
        workFlow.setIdentify(customer.getIdentity());
        workFlow.setCreator(customer.getInviteCode());
        workFlow.setInformation(customer.getInformation());
        Member member  = memberrepository.findByinviteCode(customer.getInviteCode());
        String groupCode = member.getGroupCode();
        Group g = groupRepository.findByGroupCode(groupCode);
        String manager = g.getManager();
        workFlow.setAuditPerson(manager);
        customerLevelWorkFlowRepository.save(workFlow);
        map.put(workFlow.getCustomerId(),0);
        return ResultJson.success();
    }

    public ResultJson<?> approveApply(CustomLevelWorkFlow workFlow) {
        UserBean user = CommonUtil.getCrruentUser();
        Member member = memberrepository.findByUserId(user.getUserId());
        if (member.isLeader()) {
            workFlow.setAuditPerson(member.getUserId());
        } else {
            Group group = groupRepository.findByGroupCode(member.getGroupCode());
            Member leader = memberrepository.findById(group.getManager()).get();
            workFlow.setAuditPerson(leader.getUserId());
        }
        if (workFlow == null) {
            return ResultJson.failure(ResultCode.BAD_REQUEST);
        }
        customerLevelWorkFlowRepository.save(workFlow);
        if (workFlow.getAuditStatus() == 1) {
            String identify = workFlow.getIdentify();
            Customer customer = new Customer();
            customer.setUserId(workFlow.getCustomerId());
            customer.setIdentity(identify);
            customerRepository.save(customer);
        }
        return ResultJson.success();
    }

    public ResultJson<?> queryCustomIdentifyApply(CustomLevelWorkFlow workFlow, int pageIndex, int pageSize) {
        workFlow.setAuditPerson(CommonUtil.getCrruentUser().getUserId());
        Sort.Order orders = new Sort.Order(Sort.Direction.DESC, "updateDate");
        PageRequest pageRequest = PageRequest.of(pageIndex - 1, pageSize, Sort.by(orders));
        Page<CustomLevelWorkFlow> page = null;
        page = customerLevelWorkFlowRepository.findAll(workFlow, pageRequest);
        page.getContent().forEach(v->v.setUserName(customerRepository.findByUserId(v.getCustomerId()).getUsername()));
        PageUtil pageUtil = new PageUtil(page);
        ResultJson result = ResultJson.success();
        result.setData(pageUtil);
        return result;
    }

    public ResultJson<?> updatePriceAbout(List<BusinessPriceAccount> accounts) {
        accountRepository.saveAll(accounts);
        return ResultJson.success();
    }

    public ResultJson<?> applyToBeBusiness(ApplyInfomation infomation) {
        if (infomation == null) {
            return ResultJson.failure(ResultCode.BAD_REQUEST);
        }
        ApplyRecord businessApplyRecord = new ApplyRecord();
        BeanUtils.copyProperties(infomation, businessApplyRecord);
        businessApplyRecord.setAuditStatus(1);
        businessApplyRecord.setCreateDate(new Date());
        businessApplyRecord.setUpdateDate(new Date());
        businessApplyRecord.setCreator(infomation.getUserId());
        businessApplyRecord.setBusinessType(infomation.getBusinessType());
        businessApplyRecordRepository.save(businessApplyRecord);
        return ResultJson.success();
    }

    public ResultJson<?> queryBusinessApplyRecord(ApplyRecord record, int pageIndex, int pageSize) {
        if (record == null) {
            return ResultJson.failure(ResultCode.BAD_REQUEST);
        }
        Sort.Order orders = new Sort.Order(Sort.Direction.DESC, "updateDate");
        PageRequest pageRequest = PageRequest.of(pageIndex - 1, pageSize, Sort.by(orders));
        Page<ApplyRecord> page = null;
        if (record == null) {
            page = businessApplyRecordRepository.findAll(pageRequest);
        } else {
            page = businessApplyRecordRepository.findAll(record, pageRequest);
        }
        PageUtil pageUtil = new PageUtil(page);
        ResultJson result = ResultJson.success();
        result.setData(pageUtil);
        return result;
    }

    public ResultJson<?> operateCustomIdentifyApply(CustomLevelWorkFlow workFlow) {
        if (workFlow == null) {
            return ResultJson.failure(ResultCode.BAD_REQUEST);
        }
        workFlow.setUpdateDate(new Date());
        customerLevelWorkFlowRepository.save(workFlow);
        if (workFlow.getAuditStatus() == 0) {
            Customer one = customerRepository.findByUserId(workFlow.getCustomerId());
            one.setIdentity(workFlow.getIdentify());
            customerRepository.save(one);
        }
        map.remove(workFlow.getCustomerId());
        return ResultJson.success();
    }

    public ResultJson<?> operateBusinessApplyRecord(ApplyRecord record) {
        if (record == null || record.getUserId() == null) {
            return ResultJson.failure(ResultCode.BAD_REQUEST);
        }
        businessApplyRecordRepository.save(record);
        if (record.getAuditStatus() == 0 ) {
            Member member = memberrepository.findByUserId(record.getUserId());
            Customer customer = customerRepository.findByUserId(record.getUserId());
            if (customer != null) {
                customerRepository.deleteByUserId(record.getUserId());
            }
            //添加用户
            User user = umcRepository.findByUserId(record.getUserId());            
            userRepository.save(user);
            //添加业务组
            Group group= new Group();
            group.setManager(record.getUserId());
            addGroupByAdmin(group);
            if (member == null) {
                member = new Member();
                member.setUserId(record.getUserId());
                member.setUpdateDate(new Date());
                member.setCreateDate(new Date());
                member.setUpdator("system");
                member.setCreator("system");
                member.setInviteCode(generateInviteCode());
                member.setGroupCode(group.getGroupCode());
                member.setIsLeader(1);
               // member.setPriceType(record.getIdentify());
            }
            // 业务合伙人本身是成员
            member.setBusinessType(record.getBusinessType());
            memberrepository.save(member);
        }

        //产品合伙人
        if (record.getAuditStatus() == 0 && record.getProductorType() != null) {
           // productRepository.addProductor(record.getApplyUserId(),record.getProductCode());
        }

        return ResultJson.success();
    }

    public ResultJson<?> generateBusinessAcount() {
        Integer max = memberrepository.generateBusinessAcount();
        String nextNum = (Integer.valueOf(max) + 1)+"";
        String 	prefix = "BK";
        StringBuffer prefixBuf = new StringBuffer(prefix);
        //工号总长度8位
        int length = 8;
        int tem  = (prefix+nextNum).length();
        int  needzero = length -tem;
        for(int i=0;i<needzero;i++){
            prefixBuf.append("0");
        }
        prefixBuf.append(nextNum);
        ResultJson result = ResultJson.success();
        result.setData(prefixBuf);
        return result;
    }

    public String  generateGroupCode() {
        Integer max = groupRepository.generateGroupCode();
        String nextNum = (Integer.valueOf(max) + 1)+"";
        String 	prefix = "SG";
        StringBuffer prefixBuf = new StringBuffer(prefix);
        //业务组总长度8位
        int length = 8;
        int tem  = (prefix+nextNum).length();
        int  needzero = length -tem;
        for(int i=0;i<needzero;i++){
            prefixBuf.append("0");
        }
        prefixBuf.append(nextNum);
        return prefixBuf.toString();
    }

    public String  generateInviteCode() {
        Integer max = businessApplyRecordRepository.generateInviteCode();
        String nextNum = (Integer.valueOf(max) + 1)+"";
        String 	prefix = "";
        StringBuffer prefixBuf = new StringBuffer(prefix);
        //邀请码总长度8位
        int length = 8;
        int tem  = (prefix+nextNum).length();
        int  needzero = length -tem;
        for(int i=0;i<needzero;i++){
            Random random = new Random();
            prefixBuf.append(random.nextInt(10));
        }
        prefixBuf.append(nextNum);
        return prefixBuf.toString();
    }

    public ResultJson<?> queryInviteCode() {
        UserBean u = CommonUtil.getCrruentUser();
        Member member = memberrepository.findByUserId(u.getUserId());
        ResultJson resultJson = ResultJson.success();
        resultJson.setData(member);
        return resultJson;
    }

    public ResultJson<?> updateOrderAuditStatus(Order order) {
        int auditStatus = order.getAuditStatus();
        int status = order.getStatus();
        System.out.println("status:===>"+auditStatus);
        UserBean user = CommonUtil.getCrruentUser();
        String userId = user.getUserId();
        Member member = memberrepository.findByUserId(userId);
        if (member.isLeader()){
            if (auditStatus < 111){
                if (status == 1) {
                    order.setAuditStatus(111);
                } else {
                    order.setAuditStatus(110);
                }
            } else {
                ResultJson resultJson = ResultJson.failure(ResultCode.NORESOURCE);
                resultJson.setMsg("该订单已完成或已提交");
                return resultJson;
            }
        } else {
            if (auditStatus < 11) {
                if (status == 1) {
                    order.setAuditStatus(11);
                } else {
                    order.setAuditStatus(10);
                }
            } else {
                ResultJson resultJson = ResultJson.failure(ResultCode.NORESOURCE);
                resultJson.setMsg("该订单已提交");
                return resultJson;
            }
        }
        orderRepository.updateOrderAuditStatus(order.getOrderCode(),order.getAuditStatus());
        ResultJson resultJson = ResultJson.success();
        return resultJson;
    }

    public ResultJson<?> queryMemberIsPerson() {
        UserBean user = CommonUtil.getCrruentUser();
        String userId = user.getUserId();
        Member member = memberrepository.findByUserId(userId);
        ResultJson resultJson = ResultJson.success();
        resultJson.setData(member);
        return resultJson;
    }

    public List<OrderExcelItem> getData(OrderVo orderVo){
        PageUtil ordersByBussiness = orderService.getOrdersByBussiness(orderVo, 1, 1);
        List<Map<String,Object>> list = (List<Map<String, Object>>) ordersByBussiness.getList();
        Map<String, Object> stringObjectMap = list.get(0);
        System.out.println(stringObjectMap);
        List<Map<String,Object>> orderitems = (List<Map<String, Object>>) stringObjectMap.get("orderitems");
        List<OrderExcelItem> excelItemList = new ArrayList<>();
        for (int i = 0; i < orderitems.size(); i++) {
            Map<String, Object> objectMap = orderitems.get(i);
            System.out.println(objectMap.get("goodsSpecList"));
            List<Map<String,Object>> goodsSpecList = (List<Map<String, Object>>) objectMap.get("goodsSpecList");
            OrderExcelItem orderExcelItem = new OrderExcelItem();
            orderExcelItem.setName((String) objectMap.get("brandName"));
            orderExcelItem.setCount(Integer.parseInt(String.valueOf(objectMap.get("quantity"))));
            orderExcelItem.setSinglePrice(new BigDecimal((String) objectMap.get("price")));
            orderExcelItem.setTotalPrice(new BigDecimal((String) objectMap.get("total")));
            for (int j = 0; j < goodsSpecList.size(); j++) {
                Map<String, Object> stringObjectMap1 = goodsSpecList.get(j);
                Class<? extends OrderExcelItem> aClass = orderExcelItem.getClass();
                try {
                    System.out.println("specName=======>"+(String) stringObjectMap1.get("specName"));
                    System.out.println("fieldName======>"+"comment" + (j + 1));
                    if (i == 0) {
                        changeColumn((String) stringObjectMap1.get("specName"),"comment" + (j + 1),aClass);
                    }
                    Field field = aClass.getDeclaredField("comment" + (j + 1));
                    field.setAccessible(true);
                    field.set(orderExcelItem,stringObjectMap1.get("specValue"));
                } catch (NoSuchFieldException e) {
                    e.printStackTrace();
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            }
            excelItemList.add(orderExcelItem);
        }
        return excelItemList;
    }


    private void changeColumn(String name,String fieldName,Class itemClass){
        Field field = null;
        try {
            field = itemClass.getDeclaredField(fieldName);
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        }
        ExcelProperty annotation = field.getAnnotation(ExcelProperty.class);

        InvocationHandler invocationHandler = Proxy.getInvocationHandler(annotation);
        Field memberValues = null;
        try {
            memberValues = invocationHandler.getClass().getDeclaredField("memberValues");
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        }
        memberValues.setAccessible(true);
        Map map = null;
        try {
            map = (Map)memberValues.get(invocationHandler);
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        map.put("value",new String[]{name});

    }
}
